/*
 *  composition.cpp
 *  SoundController0002
 *
 *  Created by jiro on 11/06/15.
 *  Copyright 2011 jiro music. All rights reserved.
 *
 */

#include "composition 0039.h"

#include "../Systems/HarmonicSystem/HarmonicSystem.h"
#include "../Systems/0039/Theory0039.h"
#include "../sc/AudioRecorder.h"
#include "../sc/SoundGenerator.h"
#include "../sc/NoteInfo.h"
#include "../Systems/0039/composition 0039 util.h"
#include <vector>
#include <sstream>
#include <iomanip>
#include <iostream>

using namespace sc;
using namespace sc::hs;
using namespace std;
using namespace theory0039;

void Composition0039::Compose()
{
	Experience007();
	return;

	enum
	{
		part0,	
		part1,
		part2,
		part3,
		partCount = 4
	};
	std::vector< Section > sections;
	double dynamics = Note::pianissimo;
//	double duration = 0.0;
	int repeatCount = 1;

	SequenceElement baseElement( Note::DSharp1, 1.0, Note::E1, 1.0, dynamics, repeatCount );

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();
		section.AddSubElement( SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, 0, 4 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::E1, 5.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::E1, 6.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::DSharp1, 9.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::E1, 7.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, 0, 8 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::DSharp1, 12.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, 0, 2 ), part2 );
		section.AddSubElement( SequenceElement( Note::CSharp5, 1.0, Note::B3, 9.0 / 4.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
//		std::cout << "base repeat: " << section.GetMinRepeatCountOfBaseElement() << "\n";
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

//		section.AddSubElement( SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, 0, 2 ), part1 );
		section.AddSubElement( SequenceElement( Note::DSharp4, 1.0, Note::GSharp3, 3.0 / 2.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::E1, 6.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::G3, 1.0, Note::F4, 9.0 / 16.0, dynamics, 1 ), part1 );

//		section.AddSubElement( SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, 0, 9 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::GSharp3, 9.0 / 4.0, dynamics / 2, 5 ), part2 );
		section.AddSubElement( SequenceElement( Note::FSharp4, 1.0, Note::B1, 6.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();
		section.AddSubElement( SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::E1, 5.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F3, 1.0, Note::DSharp1, 9.0 / 2.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::E1, 7.0, dynamics, 1 ), part1 );

//		section.AddSubElement( SequenceElement( Note::E4, 1.0, Note::D4, 9.0 / 16.0, 0, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::FSharp4, 1.0, Note::B1, 6.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::E1, 5.0 / 2.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}
	
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::DSharp4, 1.0, Note::GSharp3, 3.0 / 2.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::G4, 1.0, Note::F4, 9.0 / 8.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::A4, 1.0, Note::D4, 3.0 / 2.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	repeatCount = 1;
	baseElement = SequenceElement( Note::D1, 1.0, Note::DSharp1, 1.0, dynamics, repeatCount );
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::DSharp1, 15.0 / 2.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::DSharp1, 9.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::D1, 7.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::D1, 6.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::A3, 1.0, Note::D1, 6.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::CSharp4, 1.0, Note::B1, 9.0 / 2.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::GSharp3, 9.0 / 4.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::FSharp4, 1.0, Note::B1, 6.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::DSharp1, 15.0 / 2.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::ASharp3, 1.0, Note::DSharp1, 6.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::DSharp1, 6.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::FSharp3, 1.0, Note::B1, 2.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::E3, 1.0, Note::D1, 9.0 / 2.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::FSharp3, 1.0, Note::B1, 3.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::DSharp1, 13.0, dynamics, 100 ), part2 );
		section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::DSharp1, 9.0, dynamics, 2 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	repeatCount = 1;
	baseElement = SequenceElement( Note::D1, 1.0, Note::E1, 1.0, dynamics, repeatCount );
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::FSharp4, 1.0, Note::B1, 6.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::A4, 1.0, Note::D1, 24.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	repeatCount = 1;
	baseElement = SequenceElement( Note::D1, 1.0, Note::E1, 1.0, dynamics, repeatCount );
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::E1, 8.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::E1, 7.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::E1, 5.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::E1, 6.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::E1, 12.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::F1, 11.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::F1, 11.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::E1, 10.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::E1, 8.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::E1, 12.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::E1, 7.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::E1, 15.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::E5, 1.0, Note::F1, 15.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::DSharp5, 1.0, Note::F1, 14.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	repeatCount = 1;
	baseElement = SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, dynamics, repeatCount );
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::F5, 1.0, Note::E1, 10.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::E1, 12.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::DSharp1, 16.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::E1, 14.0, dynamics, 1 ), part1 );
		
		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::DSharp1, 18.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::E1, 14.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::E1, 12.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F5, 1.0, Note::E1, 10.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::G2, 1.0, Note::DSharp1, 5.0 / 2.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::DSharp3, 1.0, Note::E1, 4.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::E1, 6.0, dynamics, 1 ), part2 );

		section.AddSubElement( SequenceElement( Note::ASharp3, 1.0, Note::DSharp1, 6.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::E1, 5.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::FSharp3, 1.0, Note::E1, 9.0 / 2.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::E3, 1.0, Note::DSharp1, 4.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::FSharp5, 1.0, Note::E1, 9.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::C5, 1.0, Note::E1, 3.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::CSharp5, 1.0, Note::DSharp1, 14.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::DSharp3, 1.0, Note::E1, 4.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::A3, 1.0, Note::E1, 5.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::E1, 5.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::A3, 1.0, Note::DSharp1, 6.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	repeatCount = 1;
	baseElement = SequenceElement( Note::F1, 1.0, Note::FSharp1, 1.0, dynamics, repeatCount );
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		for ( int i = 0; i < 31; i++ )
		{
			section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::FSharp1, 13.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::FSharp5, 1.0, Note::F1, 13.0, dynamics, 1 ), part1 );
		}
		section.AddSubElement( SequenceElement( Note::F5, 1.0, Note::ASharp3, 3.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::FSharp1, 9.0 / 2.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp3, 1.0, Note::FSharp1, 5.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::FSharp1, 13.0 / 2.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::C4, 1.0, Note::F1, 6.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::FSharp4, 1.0, Note::D1, 10.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::E5, 1.0, Note::FSharp1, 15.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::C5, 1.0, Note::FSharp1, 12.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::DSharp5, 1.0, Note::FSharp1, 15.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::FSharp1, 18.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::FSharp1, 12.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::FSharp1, 10.0, dynamics, 1 ), part1 );


		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::FSharp1, 10.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::FSharp1, 11.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::FSharp1, 15.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::FSharp1, 7.0, dynamics, 1 ), part2 );
		
		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::FSharp1, 13.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::F1, 11.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::FSharp1, 15.0 / 2.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp5, 1.0, Note::FSharp1, 9.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F5, 1.0, Note::B1, 12.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::E5, 1.0, Note::GSharp1, 13.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::ASharp1, 7.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::G4, 1.0, Note::ASharp1, 7.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::FSharp1, 10.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::A4, 1.0, Note::FSharp1, 10.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::F1, 10.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	repeatCount = 1;
	baseElement = SequenceElement( Note::E1, 1.0, Note::F1, 1.0, dynamics, repeatCount );
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		for ( int i = 0; i < 23; i++ )
		{
			section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::E1, 8.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::E1, 10.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::E1, 14.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::F1, 11.0, dynamics, 1 ), part1 );
		}

		for ( int i = 0; i < 23; i++ )
		{
			section.AddSubElement( SequenceElement( Note::A4, 1.0, Note::F1, 10.0, dynamics, 1 ), part2 );
		}
		for ( int i = 0; i < 23; i++ )
		{
			section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::F1, 11.0, dynamics, 1 ), part2 );
			section.AddSubElement( SequenceElement( Note::A4, 1.0, Note::E1, 11.0, dynamics, 1 ), part2 );
		}

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		for ( int i = 0; i < 43; i++ )
		{
			section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::E1, 8.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::E1, 8.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::E1, 8.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::GSharp4, 1.0, Note::E1, 8.0, dynamics, 1 ), part1 );
		}
		for ( int i = 0; i < 51; i++ )
		{
			section.AddSubElement( SequenceElement( Note::FSharp4, 1.0, Note::F1, 8.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::E1, 4.0, dynamics, 1 ), part1 );
		}
//		cout << "part1: " << section.GetDuration( part1, true ) << "\n";

		for ( int i = 0; i < 23; i++ )
		{
			section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::F1, 11.0, dynamics, 1 ), part2 );
			section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::F1, 11.0, dynamics, 1 ), part2 );
		}
		for ( int i = 0; i < 23; i++ )
		{
			section.AddSubElement( SequenceElement( Note::C5, 1.0, Note::E1, 13.0, dynamics, 1 ), part2 );
			section.AddSubElement( SequenceElement( Note::B4, 1.0, Note::F1, 11.0, dynamics, 1 ), part2 );
		}
//		cout << "part2: " << section.GetDuration( part2, true ) << "\n";

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );

	}

	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();
		
		for ( int i = 0; i < 127; i++ )
		{
			section.AddSubElement( SequenceElement( Note::D5, 1.0, Note::F1, 12.0, dynamics, 1 ), part1 );
			section.AddSubElement( SequenceElement( Note::CSharp5, 1.0, Note::E1, 12.0, dynamics, 1 ), part2 );
		}

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	repeatCount = 1;
	baseElement = SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, dynamics, repeatCount );
	sections.push_back( Section( baseElement, partCount ) );
	{
		Section& section = sections.back();

		section.AddSubElement( SequenceElement( Note::DSharp1, 1.0, Note::E1, 1.0, 0.0, 2 ), part1 );
		section.AddSubElement( SequenceElement( Note::GSharp3, 1.0, Note::E1, 5.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::DSharp1, 6.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::F4, 1.0, Note::E1, 9.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::D4, 1.0, Note::E1, 7.0, dynamics, 1 ), part1 );
		section.AddSubElement( SequenceElement( Note::B3, 1.0, Note::E1, 6.0, dynamics, 1 ), part1 );

		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::DSharp1, 12.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::CSharp5, 1.0, Note::B3, 9.0 / 4.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::ASharp4, 1.0, Note::DSharp1, 12.0, dynamics, 1 ), part2 );
		section.AddSubElement( SequenceElement( Note::CSharp5, 1.0, Note::B1, 9.0 / 4.0, dynamics, 1 ), part2 );

		section.SetRepeatCountOfBaseElement( section.GetMinRepeatCountOfBaseElement() );
	}

	{
		AudioRecorder32 sectionRecorder( 2, 1 );
		const Section& section = sections.back();
		double time = 0.0;
		for ( int j = 0; j < partCount; j++ )
		{
			std::vector< std::vector< const sc::SoundElement32* > > soundElemntsList = section.ToSoundElements( j );
			if ( soundElemntsList.empty() )
			{
				continue;
			}

			time = 0.0;
			for ( int j = 0, soundElementsListCount = soundElemntsList.size(); j < soundElementsListCount; j++ )
			{
				std::vector< const sc::SoundElement32* >& soundElements = soundElemntsList[ j ];
				for ( size_t i = 0, count = soundElements.size(); i < count; i++ )
				{
//					std::cout << soundElements[ i ]->ToString() << " " << soundElements[ 0 ]->GetDuration() << std::endl;
					sectionRecorder.Record( 0, 0, time, soundElements[ i ], 0.5, 0.5 );
				}
				time += soundElements[ 0 ]->GetDuration();
			}
		}
		std::stringstream ss;
		ss << "/Users/jiro/temporary/00" << 39 << "_section[last].wav";
		cout << "output: " << ss.str() << "\n";
		sectionRecorder.OutputAudioFile( ss.str() );
	}

	//	output whole sections
	double time = 0.0;
	AudioRecorder32 recorder( 2, 1 );
	for ( int k = 0, sectionCount = sections.size(); k < sectionCount; k++ )
	{
		AudioRecorder32 sectionRecorder( 2, 1 );
		double sectionTime = 0.0;
		const Section& section = sections[ k ];
		double timeLastEnd = time;
		for ( int j = 0; j < partCount; j++ )
		{
			std::vector< std::vector< const sc::SoundElement32* > > soundElemntsList = section.ToSoundElements( j );
			if ( soundElemntsList.empty() )
			{
				continue;
			}

			time = timeLastEnd;
			sectionTime = 0.0;
			for ( int j = 0, soundElementsListCount = soundElemntsList.size(); j < soundElementsListCount; j++ )
			{
				std::vector< const sc::SoundElement32* >& soundElements = soundElemntsList[ j ];
				for ( size_t i = 0, count = soundElements.size(); i < count; i++ )
				{
//					std::cout << soundElements[ i ]->ToString() << " " << soundElements[ 0 ]->GetDuration() << std::endl;
					recorder.Record( 0, 0, time, soundElements[ i ], 0.5, 0.5 );
					sectionRecorder.Record( 0, 0, sectionTime, soundElements[ i ], 0.5, 0.5 );
				}
				time += soundElements[ 0 ]->GetDuration();
				sectionTime += soundElements[ 0 ]->GetDuration();
			}
		}
		std::stringstream ss;
		ss << "/Users/jiro/temporary/00" << 39 << "_section[" << k + 1 << "].wav";
		cout << "output: " << ss.str() << "\n";
		sectionRecorder.OutputAudioFile( ss.str() );

		time = timeLastEnd + section.GetTotalDuration();
	}
	std::stringstream ss;
	ss << "/Users/jiro/temporary/00" << 39 << ".wav";
	recorder.OutputAudioFile( ss.str() );

}

void Composition0039::Experience007()
{
	ChordList chords;	//	contain whole chord in this composition
	sc::hs::Chord chord;
	Sound::WaveType waveType = Sound::SingleSineWave;
	double dynamics = Note::mezzoForte;

//	for ( int i = 0; i < 12; i++ )
	int i = 1;
	{
		chord.clear();
		chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 + 4 + i ), dynamics ) );
		chords.push_back( chord );
	}

	int count = chords.size();
	const int harmonicsMax = 16;
	for ( int i = 0; i < count; i++ )
	{
		sc::hs::Chord chord = chords[ i ];
		cout << "========================================\n" << chord.ToString() 
			 << "\n"
			 << "========================================\n\n";
		Sound::NearbyWellTemperamentNotes nearbyNotes = chord.GetNearbyWellTemperamentNotes();

		std::vector< Sound::NearbyWellTemperamentNotes > sortedNotesList;
		theory0039::Theory::Sort( nearbyNotes, sortedNotesList );
		cout << Sound::ToString( sortedNotesList, harmonicsMax, true, false, false ) << "\n";
//		cout << Sound::ToString( sortedNotesList, harmonicsMax, true, true ) << "\n";
		cout << "\n";
	}
}

void Composition0039::Experience006()
{
	Experience004();
//	Experience005();

	AudioRecorder32 recorder( 2, 1 );
	enum
	{
		Layer0,
		Layer1,
		Layer2,
		Layer3,
		LayerCount,
	};
	double time = 0;
	double howlFreqs[ LayerCount ] = { 0 };
	double durations[ LayerCount ] = { 0 };
	double beatCounts[ LayerCount ] = { 0 };
	std::vector< const SoundElement32* > elements;

	sc::hs::Chord chord;
	Sound::WaveType waveType = Sound::SingleSineWave;
	double dynamics = Note::mezzoForte;

	Note::MidiNumber notes[ LayerCount ][ 64 ];
	double freqs[ LayerCount ][ 64 ];
	double duras[ LayerCount ][ 64 ];
//	int counts[ LayerCount ][ 64 ];
	int repeatCount = 0;
	double duration = 0;

	//	layer 0
	chord.clear();
	time = 0;
	notes[ Layer0 ][ 0 ] = Note::DSharp1;
	notes[ Layer0 ][ 1 ] = Note::E1;
	howlFreqs[ Layer0 ] = fabs( WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] ) - WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] ) );
	chord.push_back( Sound( waveType, notes[ Layer0 ][ 0 ], dynamics ) );
	chord.push_back( Sound( waveType, notes[ Layer0 ][ 1 ], dynamics ) );
	beatCounts[ Layer0 ] = 25;
	durations[ Layer0 ] = beatCounts[ Layer0 ] * ( 1.0 / howlFreqs[ Layer0 ] );

	time = 0.0;
	repeatCount = 1;
	elements = SoundListToSoundElements( chord, durations[ Layer0 ] );
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
	time += durations[ Layer0 ];
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
	time += durations[ Layer0 ];
	duration = durations[ Layer0 ];
	cout << duration << endl;

	//	layer 1
	notes[ Layer1 ][ 2 ] = Note::DSharp2;
	notes[ Layer1 ][ 3 ] = Note::E2;
	chord.push_back( Sound( waveType, notes[ Layer1 ][ 2 ], Note::pianississimo ) );
	chord.push_back( Sound( waveType, notes[ Layer1 ][ 3 ], Note::pianississimo ) );
	howlFreqs[ Layer1] = fabs( WellTemperament::GetFrequency( notes[ Layer1 ][ 2 ] ) - WellTemperament::GetFrequency( notes[ Layer1 ][ 3 ] ) );
	beatCounts[ Layer1 ] = 40;
//	beatCounts[ Layer1 ] = 30;
	durations[ Layer1 ] = beatCounts[ Layer1 ] * ( 1.0 / howlFreqs[ Layer1 ] );

	time = 0.0;
	duration = 0.0;
	repeatCount = 1;
	elements = SoundListToSoundElements( chord, durations[ Layer1 ] );
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
	time += durations[ Layer1 ];
	duration += durations[ Layer1 ];
	cout << duration << endl;

//	time += 7.0 / howlFreqs[ Layer0 ];
	beatCounts[ Layer1 ] = 30;
//	beatCounts[ Layer1 ] = 16;
	durations[ Layer1 ] = beatCounts[ Layer1 ] * ( 1.0 / howlFreqs[ Layer1 ] );
	elements = SoundListToSoundElements( chord, durations[ Layer1 ] );
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
	time += durations[ Layer1 ];

	time = durations[ Layer0 ] + 10.0 / howlFreqs[ Layer0 ];
	notes[ Layer1 ][ 0 ] = Note::ASharp4;
	freqs[ Layer1 ][ 0 ] = 12.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] );
	chord.push_back( Sound( waveType, notes[ Layer1 ][ 0 ], Note::pianissimo ) );
	chord.push_back( Sound( freqs[ Layer1 ][ 0 ], Note::pianissimo ) );
	howlFreqs[ Layer1 ] = fabs( WellTemperament::GetFrequency( notes[ Layer1 ][ 0 ] ) - freqs[ Layer1 ][ 0 ] );
	beatCounts[ Layer1 ] = 1;
	durations[ Layer1 ] = beatCounts[ Layer1 ] * ( 1.0 / howlFreqs[ Layer1 ] );
	elements = SoundListToSoundElements( chord, durations[ Layer1 ] );
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );

	time = durations[ Layer0 ] + 18.0 / howlFreqs[ Layer0 ];
	elements = SoundListToSoundElements( chord, durations[ Layer1 ] );
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );

	//	layer 2
/*
note: G#4(415.305Hz) is near by E2(82.4069)'s 5th(412.034Hz), ∂=3.27025Hz
note: B4(493.883Hz) is near by E2(82.4069)'s 6th(494.441Hz), ∂=0.558034Hz
note: F5(698.456Hz) is near by D#2(77.7817)'s 9th(700.036Hz), ∂=1.57925Hz
note: D5(587.33Hz) is near by E2(82.4069)'s 7th(576.848Hz), ∂=10.4813Hz
*/
	chord.clear();
	dynamics = Note::pianississimo;
	beatCounts[ Layer2 ] = 1;

	notes[ Layer2 ][ 0 ] = Note::GSharp3;
	notes[ Layer2 ][ 1 ] = Note::B3;
	notes[ Layer2 ][ 2 ] = Note::F4;
	notes[ Layer2 ][ 3 ] = Note::D4;
	freqs[ Layer2 ][ 0 ] = 5.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] );
	freqs[ Layer2 ][ 1 ] = 6.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] );
	freqs[ Layer2 ][ 2 ] = 9.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] );
	freqs[ Layer2 ][ 3 ] = 7.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] );

	duration = 0.0;
	for ( int i = 0; i < 4; i++ )
	{
		duration += 1.0 / fabs( WellTemperament::GetFrequency( notes[ Layer2 ][ i ] ) - freqs[ Layer2 ][ i ] );
		cout << "\t" << i << " " << ( 0.5 * 50.0 * 1.0 ) / fabs( WellTemperament::GetFrequency( notes[ Layer2 ][ i ] ) - freqs[ Layer2 ][ i ] ) << endl;
	}
	cout << duration << endl;

	time = ( durations[ Layer0 ] - duration ) / 2.0;
	for ( int j = 0; j < 4; j++ )
	{
		chord.clear();
		chord.push_back( Sound( waveType, notes[ Layer2 ][ j ], dynamics ) );
		chord.push_back( Sound( freqs[ Layer2 ][ j ], dynamics ) );
		howlFreqs[ Layer2 ] = fabs( WellTemperament::GetFrequency( notes[ Layer2 ][ j ] ) - freqs[ Layer2 ][ j ] );
		durations[ Layer2 ] = beatCounts[ Layer2 ] * ( 1.0 / howlFreqs[ Layer2 ] );
		elements = SoundListToSoundElements( chord, durations[ Layer2 ] );
		recorder.Record( 0, 0, time, elements, 0.65, 0.35 );
		time += durations[ Layer2 ];
	}

	time = beatCounts[ Layer0 ] / howlFreqs[ Layer0 ];
	notes[ Layer2 ][ 0 ] = Note::ASharp3;
	notes[ Layer2 ][ 1 ] = Note::GSharp2;
	notes[ Layer2 ][ 2 ] = Note::FSharp3;
	notes[ Layer2 ][ 3 ] = Note::B3;
	freqs[ Layer2 ][ 0 ] = 6.0 * WellTemperament::GetFrequency( Note::DSharp1 );
	freqs[ Layer2 ][ 1 ] = ( 5.0 / 2.0 ) * WellTemperament::GetFrequency( Note::E1 );
	freqs[ Layer2 ][ 2 ] = ( 9.0 / 2.0 ) * WellTemperament::GetFrequency( Note::E1 );
	freqs[ Layer2 ][ 3 ] = 6.0 * WellTemperament::GetFrequency( Note::E1 );
	duration = 0.0;
	for ( int i = 0; i < 4; i++ )
	{
		duration += 1.0 / fabs( WellTemperament::GetFrequency( notes[ Layer2 ][ i ] ) - freqs[ Layer2 ][ i ] );
	}
	for ( int i = 0; i < 4; i++ )
	{
		chord.clear();
		chord.push_back( Sound( waveType, notes[ Layer2 ][ i ], dynamics ) );
		chord.push_back( Sound( freqs[ Layer2 ][ i ], dynamics ) );
		howlFreqs[ Layer2 ] = fabs( WellTemperament::GetFrequency( notes[ Layer2 ][ i ] ) - freqs[ Layer2 ][ i ] );
		durations[ Layer2 ] = beatCounts[ Layer2 ] * ( 1.0 / howlFreqs[ Layer2 ] );
		elements = SoundListToSoundElements( chord, durations[ Layer2 ] );
		recorder.Record( 0, 0, time, elements, 0.65, 0.35 );
		time += durations[ Layer2 ];
	}
	time += ( durations[ Layer0 ] );

	//	layer 3
/*
note: G#3(207.652Hz) is near by E1(41.2034)'s 5th(206.017Hz), ∂=1.63513Hz
note: D4(293.665Hz) is near by E1(41.2034)'s 7th(288.424Hz), ∂=5.24066Hz
note: A#3(233.082Hz) is near by D#1(38.8909)'s 6th(233.345Hz), ∂=0.263357Hz
note: F#3(184.997Hz) is near by D#1(38.8909)'s 5th(194.454Hz), ∂=9.45715Hz
note: G3(195.998Hz) is near by D#1(38.8909)'s 5th(194.454Hz), ∂=1.54335Hz
*/
	notes[ Layer3 ][ 0 ] = Note::GSharp1;
	notes[ Layer3 ][ 1 ] = Note::D2;
	notes[ Layer3 ][ 2 ] = Note::ASharp3;
	notes[ Layer3 ][ 3 ] = Note::FSharp3;
	notes[ Layer3 ][ 4 ] = Note::G3;
	freqs[ Layer3 ][ 0 ] = 0.25 * 5.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] );
	freqs[ Layer3 ][ 1 ] = 0.25 * 7.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] );
	freqs[ Layer3 ][ 2 ] = 6.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] );
	freqs[ Layer3 ][ 3 ] = 0.5 * 9.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] );
	freqs[ Layer3 ][ 4 ] = 5.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] );

	duration = 0.0;
	for ( int i = 0; i < 5; i++ )
	{
		duras[ Layer3 ][ i ] = 1.0 / fabs( WellTemperament::GetFrequency( notes[ Layer3 ][ i ] ) - freqs[ Layer3 ][ i ] );
		cout << "\t" << i << " " << ( 0.5 * 50.0 * 1.0 ) / fabs( WellTemperament::GetFrequency( notes[ Layer3 ][ i ] ) - freqs[ Layer3 ][ i ] ) << endl;
		duration += duras[ Layer3 ][ i ];
	}
	cout << duration << endl;

	beatCounts[ Layer3 ] = 1;
	time = ( durations[ Layer0 ] - duration ) / 2.0;
	for ( int j = 0; j < 5; j++ )
	{
		chord.clear();
		chord.push_back( Sound( waveType, notes[ Layer3 ][ j ], dynamics ) );
		chord.push_back( Sound( freqs[ Layer3 ][ j ], dynamics ) );
		howlFreqs[ Layer3 ] = fabs( WellTemperament::GetFrequency( notes[ Layer3 ][ j ] ) - freqs[ Layer3 ][ j ] );
		durations[ Layer3 ] = beatCounts[ Layer3 ] * ( 1.0 / howlFreqs[ Layer3 ] );
		elements = SoundListToSoundElements( chord, durations[ Layer3 ] );
		recorder.Record( 0, 0, time, elements, 0.45, 0.55 );
		time += durations[ Layer3 ];
	}

	notes[ Layer3 ][ 0 ] = Note::F3;
	notes[ Layer3 ][ 1 ] = Note::D3;
	notes[ Layer3 ][ 2 ] = Note::B3;
	notes[ Layer3 ][ 3 ] = Note::G2;
	freqs[ Layer3 ][ 0 ] = ( 9.0 / 2.0 ) * WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] );
	freqs[ Layer3 ][ 1 ] = ( 15.0 / 4.0 ) * WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] );
	freqs[ Layer3 ][ 2 ] = 6.0 * WellTemperament::GetFrequency( notes[ Layer0 ][ 1 ] );
	freqs[ Layer3 ][ 3 ] = ( 5.0 / 2.0 ) * WellTemperament::GetFrequency( notes[ Layer0 ][ 0 ] );

	duration = 0.0;
	for ( int i = 0; i < 4; i++ )
	{
		duration += 1.0 / fabs( WellTemperament::GetFrequency( notes[ Layer3 ][ i ] ) - freqs[ Layer3 ][ i ] );
		cout << "\t" << i << " " << 1.0 / fabs( WellTemperament::GetFrequency( notes[ Layer3 ][ i ] ) - freqs[ Layer3 ][ i ] ) << endl;
	}

	time = durations[ Layer0 ] + fabs( durations[ Layer0 ] - duration ) / 2.0;
	for ( int i = 0; i < 4; i++ )
	{
		chord.clear();
		chord.push_back( Sound( waveType, notes[ Layer3 ][ i ], dynamics ) );
		chord.push_back( Sound( freqs[ Layer3 ][ i ], dynamics ) );
		howlFreqs[ Layer3 ] = fabs( WellTemperament::GetFrequency( notes[ Layer3 ][ i ] ) - freqs[ Layer3 ][ i ] );
		durations[ Layer3 ] = beatCounts[ Layer3 ] * ( 1.0 / howlFreqs[ Layer3 ] );
		elements = SoundListToSoundElements( chord, durations[ Layer3 ] );
		recorder.Record( 0, 0, time, elements, 0.45, 0.55 );
		time += durations[ Layer3 ];
	}

	//	output sound
	std::stringstream ss;
	ss << "/Users/jiro/temporary/composition0039.wav";
	recorder.OutputAudioFile( ss.str() );
}

void Composition0039::Experience005()
{
	sc::hs::Chord chord;
	Sound::WaveType waveType = Sound::SingleSineWave;
	double dynamics = Note::mezzoForte;
	AudioRecorder32 recorder( 2, 1 );
	double time = 0.0;
	double duration = 8.0;
	std::vector< const SoundElement32* > elements;

	chord.push_back( Sound( waveType, Note::DSharp1, dynamics ) );
	chord.push_back( Sound( waveType, Note::D1, dynamics ) );
	elements = SoundListToSoundElements( chord, duration );
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
	time += duration;

	chord.clear();
	chord.push_back( Sound( waveType, Note::F1, dynamics ) );
	chord.push_back( Sound( waveType, Note::FSharp1, dynamics ) );
	elements = SoundListToSoundElements( chord, duration );
	recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
	time += duration;

	std::stringstream ss;
	ss << "/Users/jiro/temporary/portion_experience0039.wav";
	recorder.OutputAudioFile( ss.str() );
}

void Composition0039::Experience004()
{
//	return;
	ChordList chords;	//	contain whole chord in this composition
	sc::hs::Chord chord;
	Sound::WaveType waveType = Sound::SingleSineWave;
	double dynamics = Note::mezzoForte;

	chord.clear();
//	chord.push_back( Sound( waveType, Note::DSharp0, dynamics ) );
//	chord.push_back( Sound( waveType, Note::E0, dynamics ) );
//	chord.push_back( Sound( waveType, Note::DSharp1, dynamics ) );
//	chord.push_back( Sound( waveType, Note::E1, dynamics ) );
//	chord.push_back( Sound( waveType, Note::DSharp2, dynamics ) );
//	chord.push_back( Sound( waveType, Note::E2, dynamics ) );
//	chord.push_back( Sound( waveType, Note::DSharp3, dynamics ) );
//	chord.push_back( Sound( waveType, Note::E3, dynamics ) );
//	chord.push_back( Sound( waveType, Note::DSharp4, dynamics ) );
//	chord.push_back( Sound( waveType, Note::E4, dynamics ) );

	chord.push_back( Sound( waveType, Note::F1, dynamics ) );
	chord.push_back( Sound( waveType, Note::FSharp1, dynamics ) );
	chords.push_back( chord );

	chord.clear();
	chord.push_back( Sound( waveType, Note::E1, dynamics ) );
	chord.push_back( Sound( waveType, Note::C1, dynamics ) );
	chords.push_back( chord );

	chord.clear();
	chord.push_back( Sound( waveType, Note::ASharp1, dynamics ) );
	chord.push_back( Sound( waveType, Note::B1, dynamics ) );
	chords.push_back( chord );

	chord.clear();
	chord.push_back( Sound( waveType, Note::D1, dynamics ) );
	chord.push_back( Sound( waveType, Note::B1, dynamics ) );
	chord.push_back( Sound( waveType, Note::F1, dynamics ) );
	chord.push_back( Sound( waveType, Note::GSharp1, dynamics ) );
	chords.push_back( chord );

	int count = chords.size();
	const int harmonicsMax = 16;
	for ( int i = 0; i < count; i++ )
	{
		sc::hs::Chord chord = chords[ i ];
		cout << "========================================\n" << chord.ToString() 
			 << "\n"
			 << "========================================\n\n";
		Sound::NearbyWellTemperamentNotes nearbyNotes = chord.GetNearbyWellTemperamentNotes();
//		cout << howls.ToString( 0, harmonicsMax ) << "\n";
//		HowlSet howls = chord.GetHowlSet();
//		cout << Sound::ToString( nearbyNotes, harmonicsMax, true ) << "\n";

		std::vector< Sound::NearbyWellTemperamentNotes > sortedNotesList;
		theory0039::Theory::Sort( nearbyNotes, sortedNotesList );
		cout << Sound::ToString( sortedNotesList, harmonicsMax, true, false, true ) << "\n";
		cout << "\n";
	}

//	//	output sound	
//	AudioRecorder32 recorder( 2, 1 );
//	double time = 0.0;
//	double duration = 4.0;
//	count = chords.size();
//	for ( size_t i = 0; i < count; i++ )
//	{
//		std::vector< const SoundElement32* > elements;
//		elements = SoundListToSoundElements( chords[ i ], duration );
//		recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
//		time += duration;
//	}
//	std::stringstream ss;
//	ss << "/Users/jiro/temporary/experience0039.wav";
//	recorder.OutputAudioFile( ss.str() );
}

void Composition0039::Experience()
{
	ChordList chords;	//	contain whole chord in this composition
	sc::hs::Chord chord;
	Sound::WaveType waveType = Sound::SawWave;
//	Sound::WaveType waveType = Sound::SquareWave;
//	Sound::WaveType waveType = Sound::TriangleWave;
	double dynamics = Note::mezzoForte;
//	int caseNo = 0;
//	int caseNo = 1;
	int caseNo = 2;

	//	set frequency
	{
		std::vector< NoteInfo > infos;
		double duration = 12;

		infos.push_back( NoteInfo( Note::E1, duration, dynamics ) );
		infos.push_back( NoteInfo( Note::DSharp1, duration, dynamics ) );
		infos.push_back( NoteInfo( 7 * WellTemperament::GetFrequency( Note::E1 ), duration, dynamics ) );
		infos.push_back( NoteInfo( Note::D3, duration, dynamics ) );
//		infos.push_back( NoteInfo( 40 * WellTemperament::GetFrequency( Note::E1 ), duration, dynamics ) );

		for ( int i = 0; i < infos.size(); i++ )
		{
			std::cout << infos[ i ].ToString() << std::endl;
		}
		std::cout << std::setprecision( 8 ) << fabs( infos[ 0 ].frequency - infos[ 1 ].frequency )
				  << ", " << 60.0 * fabs( infos[ 0 ].frequency - infos[ 1 ].frequency ) << std::endl;

		std::vector< const SoundElement32* > elements = SoundGenerator::Generate( infos );
		AudioRecorder32 recorder( 2, 1 );
		recorder.Record( 0, 0, 0, elements, 0.5, 0.5 );
		recorder.OutputAudioFile( "/Users/jiro/temporary/000.wav" );
	}

//	return;

	switch ( caseNo ) {
	case 0:
		//	D#0, E0, B0 のオクターブ違い。
		for ( int i = 0; i < 5; i++ )
		{
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::DSharp0 ), dynamics ) );
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::E0 ), dynamics ) );
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::B0 ), dynamics ) );
			chords.push_back( chord );
			chord.clear();
		}
		break;

	case 1:
		//	D#0, E0, B0 のオクターブ違い２つの組み合わせ
		for ( int i = 0; i < 5; i++ )
		{
			for ( int j = i + 1; j < 5; j++ )
			{
				chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::DSharp0 ), dynamics ) );
				chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::E0 ), dynamics ) );
				chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::B0 ), dynamics ) );
				chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * j + Note::DSharp0 ), dynamics ) );
				chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * j + Note::E0 ), dynamics ) );
				chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * j + Note::B0 ), dynamics ) );
				chords.push_back( chord );
				chord.clear();
			} 
		}	
		break;

	case 2:
		//	D#1, E1, D4。シベリウスのピアノ音源で鳴らすと良いのでやってみる。
		for ( int i = 0; i < 2; i++ )
		{
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::DSharp0 ), dynamics ) );
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::E0 ), dynamics ) );
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::D3 ), dynamics ) );
			chords.push_back( chord );
			chord.clear();
		}
		for ( int i = 0; i < 2; i++ )
		{
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::DSharp0 ), dynamics ) );
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::E0 ), dynamics ) );
			chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( 12 * i + Note::D4 ), dynamics ) );
			chords.push_back( chord );
			chord.clear();
		}
		break;

	default:
		break;

	}

	//	display to browse
	for ( size_t i = 0; i < chords.size(); i++ )
	{
//		break;
		
		std::cout << i << std::endl;
		const HowlSet& howlList = chords[ i ].GetHowlSet();
		std::cout << chords[ i ].ToString() << std::endl;
		std::cout << howlList.ToString() << "\n\n";

		std::multiset< Howl >::const_iterator iter = howlList.begin();
		for ( int j = 0; iter != howlList.end(); iter++, j++ )
		{
			Howl howl = *iter;
			const HarmonicSound& hs1 = howl.GetHarmonicSound( true );
			const HarmonicSound& hs2 = howl.GetHarmonicSound( false );
			std::vector< NoteInfo > infos;
			double duration = 4.0;
			double dynamics = Note::mezzoForte;
			
			infos.push_back( NoteInfo( hs1.GetFrequency(), duration, dynamics ) );
			infos.push_back( NoteInfo( hs2.GetFrequency(), duration, dynamics ) );

			double time = 0.0;
			AudioRecorder32 recorder( 2, 1 );
			std::vector< const SoundElement32* > elements;
			std::stringstream ss;

			ss << "/Users/jiro/temporary/sub" << i << "-" << j << ".wav";
			elements = SoundGenerator::Generate( infos );
			recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
			recorder.OutputAudioFile( ss.str() );
		}
	}

	//	output to debug
	for ( size_t i = 0; i < chords.size(); i++ )
	{
		double time = 0.0;
		double duration = 16.0;
		AudioRecorder32 recorder( 2, 1 );
		std::vector< const SoundElement32* > elements;
		elements = SoundListToSoundElements( chords[ i ], duration );
		recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
		time += duration;
		
		std::stringstream ss;
		ss << "/Users/jiro/temporary/"  << caseNo << "-" << i << ".wav";
		recorder.OutputAudioFile( ss.str() );
	}
}

void Composition0039::Experience001()
{
	//	system0039 に出てくる半音程を低音で演奏したときに生じるうなりを計算
	sc::Note::MidiNumber notes[] = {
		sc::Note::D2,
		sc::Note::DSharp2,
		sc::Note::E2,
		sc::Note::F2,
		sc::Note::FSharp2,
		sc::Note::G2,
		sc::Note::GSharp2,
		sc::Note::ASharp2,
		sc::Note::B2,
		sc::Note::C3,
	};

	for ( int i = 0; i < sizeof( notes ) / sizeof( sc::Note::MidiNumber ) - 1; i++ )
	{
		sc::Note::MidiNumber note0 = notes[ i ];
		sc::Note::MidiNumber note1 = notes[ i + 1 ];
		if ( note1 - note0 != 1 )
		{
			continue;
		}

		double harmonics = 2.0;
		double delta = harmonics * ( WellTemperament::GetFrequency( note1 ) - WellTemperament::GetFrequency( note0 ) );
		std::cout
			<< sc::Note::ToString( note0 ) << " " << sc::Note::ToString( note1 )  << ":	∂ = "
			<< delta << ", quarter: " << 60 * delta << ", sixteenth: " <<  15 * delta
			<< std::endl;
	}
}

void Composition0039::Experience002()
{
	ChordList chords;	//	contain whole chord in this composition
	sc::hs::Chord chord;
//	Sound::WaveType waveType = Sound::SawWave;
	Sound::WaveType waveType = Sound::SquareWave;
//	Sound::WaveType waveType = Sound::TriangleWave;
	double dynamics = Note::mezzoForte;

	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B2 ), dynamics ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::GSharp3 ), dynamics ) );
	chords.push_back( chord );
	chord.clear();

	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B2 ), Note::mezzoPiano ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::GSharp3 ), Note::mezzoPiano ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::DSharp5 ), dynamics ) );
	chords.push_back( chord );
	chord.clear();

	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::C3 ), Note::mezzoPiano ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::A3 ), Note::mezzoPiano ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::E5 ), dynamics ) );
	chords.push_back( chord );
	chord.clear();


	//	output
	AudioRecorder32 recorder( 2, 1 );
	double time = 0.0;
	double duration = 8.0;
	for ( size_t i = 0; i < chords.size(); i++ )
	{
		std::vector< const SoundElement32* > elements;
		elements = SoundListToSoundElements( chords[ i ], duration );
		recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
		time += duration;
	}
	std::stringstream ss;
	ss << "/Users/jiro/temporary/" << 39 << ".wav";
	recorder.OutputAudioFile( ss.str() );

}

void Composition0039::Experience003()
{
	sc::hs::Chord chord;
	ChordList chords;
//	Sound::WaveType waveType = Sound::SingleSinWave;
//	Sound::WaveType waveType = Sound::TriangleWave;
	Sound::WaveType waveType = Sound::SawWave;
	double dynamics = Note::piano;

	chord.clear();
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::DSharp4 ), dynamics ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::E4 ), dynamics ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B4 ), dynamics ) );
	chords.push_back( chord );

	chord.clear();
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::G6 ), dynamics ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::E4 ), dynamics ) );
	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B4 ), dynamics ) );
	chords.push_back( chord );

	const Sound::NearbyWellTemperamentNotes& nearbyNotes = chord.GetNearbyWellTemperamentNotes();
	const HowlSet& howls = chord.GetHowlSet();

	cout << Sound::ToString( nearbyNotes, 16, false, false, true ) << endl;
	cout << howls.ToString( 0, 5 ) << endl;

//	chord.clear();
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::G6 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::E4 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B4 ), dynamics ) );
//	chords.push_back( chord );

//	chord.clear();
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::DSharp4 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::E4 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B4 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::FSharp6 ), dynamics ) );
//	chords.push_back( chord );
//
//	chord.clear();
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::DSharp4 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::FSharp6 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B4 ), dynamics ) );
//	chords.push_back( chord );

//	chord.clear();
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::DSharp5 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::BFlat5 ), dynamics ) );
//	chord.push_back( Sound( waveType, static_cast< Note::MidiNumber >( Note::B4 ), dynamics ) );
//	chords.push_back( chord );

//	const Sound::NearbyWellTemperamentNotes& nearbyNotes = chord.GetNearbyWellTemperamentNotes();
//	const HowlSet& howls = chord.GetHowlSet();
//	cout << Sound::ToString( nearbyNotes ) << endl;
//	cout << howls.ToString() << endl;

	chord.clear();

	//	output
	AudioRecorder32 recorder( 2, 1 );
	double time = 0.0;
	double duration = 8.0;
	for ( size_t i = 0; i < chords.size(); i++ )
	{
		std::vector< const SoundElement32* > elements;
		elements = SoundListToSoundElements( chords[ i ], duration );
		recorder.Record( 0, 0, time, elements, 0.5, 0.5 );
		time += duration;
	}
	std::stringstream ss;
	ss << "/Users/jiro/temporary/" << 39 << "-" << 3 << ".wav";
	recorder.OutputAudioFile( ss.str() );
}

std::vector< const SoundElement32* > Composition0039::SoundToSoundElements( const Sound& sound, double duration ) const
{
	std::vector< const SoundElement32* > elements;
	static int phaseShiftIndex = 0;
	phaseShiftIndex++;

	std::vector< NoteInfo > noteInfos;
	const WaveFunction& function = WaveFunctionFactory::CreateXSinX( 0.5, 2 * duration );
//	const WaveFunction& function = WaveFunctionFactory::CreateXSinX( 1., 1.0 / ( 2.0 * duration ) );
//	const WaveFunction& function = WaveFunctionFactory::CreateLogXSinX( 1.0, 1.0 / ( 2.0 * duration ) );
//	const WaveFunction& function = WaveFunctionFactory::CreateSinPowerOfX( 0.0, 1.0 / ( 2.0 * duration ) );
	const WaveTable& dynamicsTable = WaveTableFactory::Create( function, sound.GetDynamics() );

//	const WaveTable& dynamicsTable = WaveTableFactory::Create( WaveTable::Type_Sine, 1.0 / ( 2.0 * duration ), 1.0 );

	if ( ( sound.GetFrequency() != -1 ) && ( sound.GetMidiNumber() == Note::MidiNumberMute ) )
	{
		noteInfos.push_back( NoteInfo( sound.GetFrequency(), duration, sound.GetDynamics(), dynamicsTable ) );
	}
	else
	{
		double frequency = WellTemperament::GetFrequency( sound.GetMidiNumber() );
		int count = sound.GetHarmonicsCount();
		for ( int i = 1; i <= count; i++ )
		{
			if ( sound.GetWaveType() == Sound::SingleSineWave )
			{
				noteInfos.push_back( 
					NoteInfo( 
						frequency, 
						duration, 
						sound.GetHarmonicAmplitude( 1 ) * sound.GetDynamics(), 
						dynamicsTable,
						0.5 * phaseShiftIndex ) );
				break;
			}

			double amplitude = sound.GetHarmonicAmplitude( i );
			if ( amplitude == 0 )
			{
				continue;
			}

			switch ( sound.GetWaveType() )
			{
			case Sound::SawWave:
				noteInfos.push_back( 
					NoteInfo( 
						i * frequency, 
						duration, 
						sound.GetHarmonicAmplitude( i ) * sound.GetDynamics(), 
						dynamicsTable, 
						0.5 * phaseShiftIndex ) );
				break;

			case Sound::SquareWave:
				if ( i % 2 == 1 )
				{
					noteInfos.push_back(
						NoteInfo(
							i * frequency, 
							duration,
							sound.GetHarmonicAmplitude( i ) * sound.GetDynamics(), 
							dynamicsTable,
							0.5 * phaseShiftIndex ) );
				}
				break;

			case Sound::TriangleWave:
				if ( i % 2 == 1 )
				{
					noteInfos.push_back(
						NoteInfo( 
							i * frequency, 
							duration, 
							sound.GetHarmonicAmplitude( i ) * sound.GetDynamics(), 
							dynamicsTable,
							0.5 * phaseShiftIndex ) );
				}
				break;
			}
		}
	}
	elements = SoundGenerator::Generate( noteInfos );
	return elements;
}

std::vector< const sc::SoundElement32* > Composition0039::SoundListToSoundElements( const ::sc::hs::SoundList& sounds, double duration ) const
{
	std::vector< const SoundElement32* > elements;
	for ( size_t i = 0; i < sounds.size(); i++ )
	{
		std::vector< const SoundElement32* > singleSoundElements;
		singleSoundElements = SoundToSoundElements( sounds[ i ], duration ); 
		for ( int j = 0; j < singleSoundElements.size(); j++ )
		{
			elements.push_back( singleSoundElements[ j ] );
		}
	}
	return elements;
}
